package func;

import java.util.ArrayList;
import java.util.Map;
import java.util.TreeMap;

public class FunctionFactoryImpl<T> implements FunctionFactory<T> {
	private ArrayList<Function<T>> l;
	private Map<String, Function<T>> map;
	private String desc;
	public FunctionFactoryImpl(ArrayList<FunctionGroup<T>> functions) {
		l = new ArrayList<Function<T>>();
		map = new TreeMap<String, Function<T>>();
		desc = "";
		for(FunctionGroup<T> fg : functions) {
			if(!desc.isEmpty())
				desc += "+";
			desc += fg.description();
			for(Function<T> f : fg.createFunctionGroup()) {
				l.add(f);
				map.put(f.description(), f);
			}
		}
	}
	@SuppressWarnings("unchecked")
	public FunctionFactoryImpl(String desc) {
		l = new ArrayList<Function<T>>();
		map = new TreeMap<String, Function<T>>();
		this.desc = desc;
		ArrayList<FunctionGroup<T>> functions = new ArrayList<FunctionGroup<T>>();
		
		try {
			functions.add((FunctionGroup<T>)new BasicTrigometricFuncs());			
		}
		catch(Exception e) {};
		try {
			functions.add((FunctionGroup<T>)new BasicIntegerFuncs());			
		}
		catch(Exception e) {};
		try {
			functions.add((FunctionGroup<T>)new BasicDoubleFuncs());			
		}
		catch(Exception e) {};
		try {
			functions.add((FunctionGroup<T>)new ConditionalIntegerFuncs());			
		}
		catch(Exception e) {};
		try {
			functions.add((FunctionGroup<T>)new ConditionalDoubleFuncs());			
		}
		catch(Exception e) {};
		try {
			functions.add((FunctionGroup<T>)new MiscFuncs());			
		}
		catch(Exception e) {};
		try {
			functions.add((FunctionGroup<T>)new MaxMinFuncs());			
		}
		catch(Exception e) {};
		
		for(FunctionGroup<T> fg : functions) {
			if(desc.indexOf(fg.description()) == -1) continue;
			for(Function<T> f : fg.createFunctionGroup()) {
				l.add(f);
				map.put(f.description(), f);
			}
		}
	}
	public String description() {
		return desc;
	}
	public Function<T> createFunction(String desc) {
		if(map.containsKey(desc))
			return map.get(desc);
		return null;
	}
	public ArrayList<Function<T>> createFunctionGroup() {
		return l;
	}

}
